package siruna.WE.FileManager;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

/**
 * Klasse die de file afhandeling zal afschermen Widgets opslaan, openen,
 * settings wegschrijven,...
 * 
 * @author Tim
 */
public class FileManager {
	// android context
	private Context context;

	/**
	 * Constructor
	 * 
	 * @param context
	 *            Android context moet doorgegeven worden bij constructie
	 */
	public FileManager(Context context) {
		this.context = context;
	}

	/**
	 * Heel de iconen op van alle geinstalleerde widgets
	 * 
	 * @return hashmap <naam widget, Bitmap>
	 */
	public HashMap<String, Bitmap> getIcons() {
		HashMap<String, Bitmap> icons = new HashMap<String, Bitmap>();
		try {
			// in deze map staan alle widgets
			File map = new File("data/data/siruna.WE/files/widgets");

			for (File f : map.listFiles()) {
				// icon bepalen en inlezen.
				File icon = new File(f.getAbsolutePath() + "/icon.jpg");
				if (icon.exists()) {
					FileInputStream fin = new FileInputStream(icon);
					Bitmap iconBitmap1 = BitmapFactory.decodeStream(fin);

					// hier reeds herschalen naar de juiste afmeting
					Bitmap iconBitmap = Bitmap.createScaledBitmap(iconBitmap1,
							100, 100, true);

					icons.put(f.getName(), iconBitmap);
					System.out.println("added: " + f.getName());
				}
			}

		} catch (Exception e) {
			Log.e("Error", "IconsError", e);
			e.printStackTrace();
		}
		return icons;
	}

	/**
	 * Geeft de start file (index.html) terug van een gegeven widget Gebruikt
	 * bij opstarten van een widget
	 * 
	 * @param widgetId
	 *            naam van de widget
	 * @param file
	 *            naam van het start bestand, in de huidige implementatie is dit
	 *            altijd index.html
	 * @return het bestand wordt meteen als string teruggegeven.
	 */
	public String getStartFile(String widgetId, String file) {
		File main = new File("data/data/siruna.WE/files/widgets/" + widgetId
				+ "/" + file);

		int ch;
		StringBuffer strContent = new StringBuffer("");

		FileInputStream fin;
		try {
			fin = new FileInputStream(main);

			while ((ch = fin.read()) != -1) {
				strContent.append((char) ch);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return strContent.toString();
	}

	/**
	 * Verwijdert de widget, gegeven door de naam s
	 * 
	 * @param s
	 *            de naam van de te verwijderen widget
	 * @return true als gelukt, false indien mislukt
	 */
	public boolean removeWidget(final String s) {
		System.out.println("Verwijder widget: "
				+ "data/data/siruna.WE/files/widgets/" + s);

		File main = new File("data/data/siruna.WE/files/widgets/" + s);

		removeFilesRec(main);

		// TODO geef true of false terug
		return true;

	}

	/**
	 * Methode om een bestand of map volledige te verwijderen, als het een map
	 * is worden ook alle onderliggende mappen verwijderd
	 * 
	 * @param f
	 *            bestand of map dat verwijderd moet worden.
	 */
	private void removeFilesRec(File f) {
		if (f.isDirectory() && f.list().length > 0) {
			for (File ff : f.listFiles()) {
				removeFilesRec(ff);
			}
			f.delete();
		} else {// file
			f.delete();
		}
	}

	/**
	 * Installeer een widget, de locatie van de widget en de naam worden
	 * meegegeven Eerst wordt de widget gedownload, daarna geunzipt
	 * 
	 * @param url
	 *            url-locatie van de widget
	 * @param name
	 *            naam van de widget
	 * @return true als gelukt, false als mislukt
	 */
	public boolean installWidget(String url, String name) {
		String temp;
		try {

			URLConnection http = new URL(url).openConnection();

			// downloadstream
			InputStream in = http.getInputStream();
			try {
				// bestand op schijf, eerst in de temp map plaatsen
				temp = "data/data/siruna.WE/files/temp/" + name + ".zip";
				File f = new File(temp);
				f.createNewFile();

				OutputStream out = new FileOutputStream(f);

				// downloaden
				try {
					byte[] buf = new byte[512];
					int read;

					while ((read = in.read(buf)) > 0)
						out.write(buf, 0, read);
				} finally {
					out.close();
				}
			} finally {
				in.close();
			}
			// bestand staat in de dir temp
			ZipFile f = new ZipFile(temp);

			// unzippen
			unzip(f, name);

			// verwijder het bestand in de temp map
			File tempo = new File(temp);
			tempo.delete();

			return true;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;

	}

	/**
	 * Unzip een gegeven zip bestand
	 * 
	 * @param f
	 *            zup bestand
	 * @param name
	 *            naam van de widget
	 */
	private void unzip(ZipFile f, String name) {
		// unzippen
		try {
			Enumeration<?> enumeration = f.entries();
			System.out.println("unzippen");

			// locatie waar de widget zal bewaard worden
			String base = "data/data/siruna.WE/files/widgets/" + name + "/";

			File f1 = new File(base);
			f1.mkdir();

			// zip bestand overlopen en unzippen
			while (enumeration.hasMoreElements()) {
				ZipEntry zipEntry = (ZipEntry) enumeration.nextElement();
				System.out.println("Unzipping: " + zipEntry.getName());

				if (zipEntry.isDirectory()) {
					System.out.println("dir: " + zipEntry.getName());

					File dir = new File(base + zipEntry.getName());
					dir.delete();
					dir.mkdir();
				} else {// geen dir
					BufferedInputStream bis = new BufferedInputStream(f
							.getInputStream(zipEntry));

					int size;
					byte[] buffer = new byte[2048];

					System.out.println("file: " + base + zipEntry.getName());

					FileOutputStream fos = new FileOutputStream(base
							+ zipEntry.getName());

					BufferedOutputStream bos = new BufferedOutputStream(fos,
							buffer.length);

					while ((size = bis.read(buffer, 0, buffer.length)) != -1) {
						bos.write(buffer, 0, size);
					}

					bos.flush();
					bos.close();
					fos.close();

					bis.close();
				}
			}

			// preferencesfile op de juiste plaats zetten + juiste naam geven
			String p = "data/data/siruna.WE/files/widgets/" + name
					+ "/preferences.xml";
			String d = "data/data/siruna.WE/files/preferences/" + name
					+ "_preferences.xml";
			File pref = new File(p);
			if (pref.exists() && !existsWidgetPreferences(name)) {
				// preferencefile is niet verplicht
				// als reeds bestaat in de map preferences, niet overschrijven !
				File dest = new File(d);
				dest.createNewFile();
				pref.renameTo(dest);

			}

		} catch (IOException e) {
			Log.e("Error", "UnzipError", e);
		}

	}

	/**
	 * Methode die gebruikt wordt bij opstarten van de applicatie, die ervoor
	 * zorgt dat de nodige directories aanwezig zijn. (als deze er nog niet
	 * zijn)
	 * 
	 */
	public void createDirs() {
		File f1 = new File("data/data/siruna.WE/files/");
		f1.mkdir();
		f1 = new File("data/data/siruna.WE/files/widgets/");
		f1.mkdir();
		f1 = new File("data/data/siruna.WE/files/temp/");
		f1.mkdir();
		f1 = new File("data/data/siruna.WE/files/preferences/");
		f1.mkdir();

	}

	/**
	 * geef de filestream terug naar de config file van de geselcteerde widget
	 * 
	 * @param geselecteerd
	 *            naam geselecteerde widget
	 * @return filestream als gelukt, null indien mislukt
	 */
	public FileInputStream getConfigFileInputStream(String geselecteerd) {
		File f = new File("data/data/siruna.WE/files/widgets/" + geselecteerd
				+ "/config.xml");
		try {
			return new FileInputStream(f);
		} catch (FileNotFoundException e) {
			Log.e("Error", "ConfigFileError", e);
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * Verwijder de preferences file van een gegeven widget. Bij verwijderen van
	 * een widget kan de gebruiker kiezen om de preferences niet te verwijderen.
	 * Als hij dezelfde widet later opnieuw iinstalleert worden de oude
	 * instellinge gebruikt
	 * 
	 * @param s
	 *            naam van de widget
	 */
	public void removeWidgetPreferences(String s) {
		String d = "data/data/siruna.WE/files/preferences/" + s
				+ "_preferences.xml";
		File pref = new File(d);

		removeFilesRec(pref);

	}

	/**
	 * Methode die teruggeeft of de gegeven widget een preferences file heeft.
	 * Dit bestand is niet verplicght
	 * 
	 * @param s
	 *            naam van de widget
	 * @return true als er een bestand is, false indien niet
	 */
	public boolean existsWidgetPreferences(String s) {
		String d = "data/data/siruna.WE/files/preferences/" + s
				+ "_preferences.xml";
		File pref = new File(d);

		return pref.exists();

	}

	/**
	 * Geeft de preferences file van een gegeven widget terug. Altijd eerst de
	 * methode existsWidgetPreferences gebruiken !
	 * 
	 * @param widgetId
	 *            naam van de widget
	 * @return het preferences bestand
	 */
	public File getPreferenceFile(String widgetId) {
		String d = "data/data/siruna.WE/files/preferences/" + widgetId
				+ "_preferences.xml";
		return new File(d);
	}

}
